home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
castools.zip
/
MODIFYEN.C
< prev
next >
Wrap
Text File
|
1990-02-13
|
8KB
|
238 lines
/*
ADDENTRY.C Function PbAddEntry: Adds an entry (individual or group) to an
open phonebook.
INPUT: Phonebook structure and filled phonebook entry structure.
OUTPUT: If successful, updates the entries field of the phonebook
structure, and sets the ID field of the entry structure.
*/
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <malloc.h>
#include <phonebk.h>
int pascal PbModifyEntry(PB *pb, int RecordID, PBE *new_entry)
{
PBE *old_entry = NULL, *group_entry = NULL;
PBEFIXED fixed_part;
char *entry_buffer;
int result;
int filenum;
int i, j; /* loop counters */
long PbSize, offset;
BYTE hw_type,
hasccc = HASCCC; /* for changing the h/w type of a group */
int red, writ; /* for checking returns from fread() and fwrite() */
int buffed_rids = pb->OBufferSize/sizeof(LONGWORD); /* whether 0 or not */
int temperrno = 0; /* for saving aside Pberrno */
Pberrno = 0; /* Initially, always reset */
/* First, check params */
if ((pb == NULL) ||
(new_entry == NULL)) {
Pberrno = INVALIDPARAMETER;
goto error_out;
}
if ((RecordID < 0) ||
(RecordID > 999)) {
Pberrno = INVALIDPARAMETER;
return(NULL);
}
/* Allocate memory for and fetch the record being changed */
old_entry = PbGetEntry(pb, NULL, NULL, RecordID);
if (!old_entry) {
Pberrno = NOENTRYPRESENT;
goto error_out;
}
/* call EntryOkToChange(); if not, free the old_entry and get out */
if ((!(entry_buffer = EntryOkToChange(pb, old_entry, new_entry)))) {
Pberrno = INVALIDCHANGE;
goto error_out;
}
/* If new entry is larger than old, put it at end of file */
if (new_entry->length > old_entry->length) {
/* Next, find the offset of the end-of-file , and set a vbl offset to it */
filenum = fileno(pb->fp);
PbSize = filelength(filenum);
if (PbSize == -1L) {
Pberrno = FILELENGTHERROR;
goto error_out;
}
offset = PbSize;
/* Attempt the append to file */
if (fseek(pb->fp, 0L, SEEK_END)) {
Pberrno = FSEEKERROR;
goto error_out;
}
writ = fwrite(entry_buffer, new_entry->length, 1, pb->fp);
if (writ != 1) {
Pberrno = CANTWRITE;
goto error_out;
}
/* If write successful, change the offset at RID and unused_bytes field */
else {
/* If the RID is in the OBuffer, change the offset there first */
if (pb->OBuffer) {
if ((RecordID >= pb->FirstOBufferRID) &&
(RecordID < pb->FirstOBufferRID + buffed_rids)) {
pb->OBuffer[RecordID - pb->FirstOBufferRID] = offset;
}
}
/* Write the changed offset to the file */
if (fseek(pb->fp, 160L + RecordID*sizeof(LONGWORD), SEEK_SET)) {
Pberrno = FSEEKERROR;
goto error_out;
}
writ = fwrite(&offset, sizeof(LONGWORD), 1, pb->fp);
if (writ != 1) {
Pberrno = CANTWRITE;
goto error_out;
}
/* Add size of old entry to the FreeBytes field */
pb->header.FreeBytes += old_entry->length;
}
}
/* The new entry is smaller, or the same size */
else {
/* Otherwise, just write the new entry where the old entry was */
/* First, there is STILL a possibility of freeing too many bytes */
if ((old_entry->length - new_entry->length + pb->header.FreeBytes)
> MAXUNUSEDBYTES) {
Pberrno = TOOMANYFREEBYTES;
goto error_out;
}
else {
pb->header.FreeBytes += old_entry->length - new_entry->length;
}
/* First, find offset of old entry */
/* no error possible, since we've gotten it already */
offset = OffsetOfEntry(pb, RecordID);
/* ...and seek to there and write the new entry in */
if (fseek(pb->fp, offset, SEEK_SET)) {
Pberrno = FSEEKERROR;
goto error_out;
}
writ = fwrite(entry_buffer, new_entry->length, 1, pb->fp);
/* If write not successful, free the memory used for old entry, and quit */
if (writ != 1) {
Pberrno = CANTWRITE;
goto error_out;
}
}
/* If size changed at all, "free bytes" was updated, so write it to file */
if (old_entry->length != new_entry->length) {
if (fseek(pb->fp, 6L, SEEK_SET)) {
Pberrno = FSEEKERROR;
goto error_out;
}
writ = fwrite(&pb->header.FreeBytes, sizeof(int), 1, pb->fp);
if (writ != 1) {
Pberrno = CANTWRITE;
goto error_out;
}
}
/* If hardware type is being changed, check out all groups that entry is a
member of: IF change is CCP-to-FaxOnly, AND any group is CCP, change
that group to FaxOnly. IF change is FaxOnly-to-CCP, any groups should
be FaxOnly. (If any AREN'T, set them and set a warning.) For any
such groups, scan their other members, looking for the first FaxOnly.
IF any found, leave the group FaxOnly. ELSE, set it to CCP. */
if (old_entry->HardwareType != new_entry->HardwareType) {
/* If the change is to FAXONLY, make sure all groups involved be FAXONLY */
if (new_entry->HardwareType == FAXONLY) {
for (i=0; i<new_entry->members; i++) {
if (HardwareTypeOf(pb, new_entry->MemberList[i], &offset) == HASCCC) {
if (fseek(pb->fp, offset, SEEK_SET)) {
Pberrno = FSEEKERROR;
goto error_out;
}
writ = fwrite(&new_entry->HardwareType, sizeof(BYTE), 1, pb->fp);
if (writ != 1) {
Pberrno = CANTWRITE;
goto error_out;
}
}
}
}
/* If change is FAXONLY to HASCCC there is even MORE work to do!
Every group involved should have been FAXONLY: check all their OTHER
members. If they are all HASCCC, then change group to HASCCC */
else {
for (i=0; i<new_entry->members; i++) {
group_entry = PbGetEntry(pb, NULL, NULL, new_entry->MemberList[i]);
for (j=0; j<group_entry->members; j++) {
/* check all members other than ours */
if (group_entry->MemberList[j] != RecordID) {
if (HardwareTypeOf(pb,
group_entry->MemberList[j],
&offset) == FAXONLY) {
break;
}
}
}
if (j == group_entry->members) { /* they were all CCP except ours */
offset = OffsetOfEntry(pb, new_entry->MemberList[i]) + 7L;
if (fseek(pb->fp, offset, SEEK_SET)) {
Pberrno = FSEEKERROR;
goto error_out;
}
writ = fwrite(&hasccc, sizeof(BYTE), 1, pb->fp);
if (writ != 1) {
Pberrno = CANTWRITE;
goto error_out;
}
} /* end of scanning other members of group the entry is member of */
} /* end of scanning all the group the entry is a member of */
} /* end of if change is FAXONLY to HASCCC */
} /* end of if hardware types differ */
/* and if we got here without any goto, all was well! */
PbFreePBE(pb, old_entry);
free(entry_buffer);
return(SUCCESS);
error_out:
if (Pberrno) {
temperrno = Pberrno;
}
if (old_entry) {
PbFreePBE(pb, old_entry);
}
if (group_entry) {
PbFreePBE(pb, group_entry);
}
if (temperrno) {
Pberrno = temperrno;
}
if (entry_buffer) {
free(entry_buffer);
}
return(FAIL);
}